四、TypeScript 教程
文档资料
ts入门教程: https://ts.xcatliu.com/
为什么要用TypeScript
- JavaScript和TypeScript的主要区别为:TypeScript是静态类型,js是动态类型(详见强类型、弱类型、静态类型、动态类型的区别)。
- 但这不意味着两者差距多大,只是类型检查的时机不同而已,TS和js根本上的差别就这一点,然而其意义却举足轻重。
- 静态类型检查可以做到early fail,即你编写的代码即使没有被执行到,一旦你编写代码时发生类型不匹配,语言在编译阶段(解释执行也一样,可以在运行前)即可发现,同时IDE也能提供大量便捷支持。对小型项目而言也许发挥不出多大优势,然而当项目规模膨胀,运行前的类型检查就大放异彩了——首先,大型项目测试调试分支覆盖困难,很多代码并不一定能够在所有条件下执行到,运行前的类型检查是减少bug的一大手段;其次,静态类型对阅读代码是友好的,在团队合作、代码维护和交接中意义不言自明;最后,IDE提供的大量便捷支持和TS本身的语法检查和代码提示自动补全让开发者提高效率,方便重构(维护过大型web项目中各种乱七八糟的js文件就能发现静态类型多美好)。
准备工作
安装
npm install -g typescript
初始化项目
tsc --init
设置js输出路径, 将tsconfig.json中的
"outDir": "./"
注释打开,也可以换成你想要编译后存放的目录,比如 './dist'自动编译ts文件, 打开一个终端,运行
tsc -w
新建demo.ts, 输入
var count:number = 100; console.log(count);
运行demo.js
node ./dist/demo.js
(一) llo world
var msg:string = 'hello world';
console.log(msg);
(二) 数据类型
// (1)布尔
let isDone: boolean = false;
// (2)数字
let decLiteral: number = 6;
// (3)字符串
let name: string = "bob";
name = "smith";
// (4)带变量字符串
let name: string = `Gene`;
let age: number = 37;
let sentence: string = `Hello, my name is ${ name }.
I'll be ${ age + 1 } years old next month.`;
// (5)数组
let list: number[] = [1, 2, 3];
let list: Array<number> = [1, 2, 3];
let list: Array<any> = [1, true, 3];
// 对象
let obj:Object = {a:2, b:3}
// any 任意类型
let aa:any = xxx;
(三) tuple类型
元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。 比
如,你可以定义一对值分别为 string 和 number 类型的元组。
let x: [string, number];
x = ['hello', 10];
x = [10, 'hello']; // 会报错
(四) 联合类型
var val:string|number
val = 12
console.log("数字为 "+ val)
val = "test"
console.log("字符串为 " + val)
(五) 接口(用来定义类型)
(1) Person是接口, 定义woman时指定了它的类型是IPerson
(2)加了?代表是可选属性
(3) 可以理解为给一个类设定规则, 有什么属性和有什么方法
(4) 应用场景: : vue路由配置可以使用到
interface Person {
username:string,
age?:number,
sayHi: ()=>string
}
var woman:Person = {
username:"翠花",
age:18,
sayHi: ():string =>{return "Hello!!!"}
}
console.log(woman.username)
console.log(woman.age)
(六) type
// 定义People类型
type People = {
name: string;
age: number;
};
// 声明变量p,p的类型为People
let p:People = {
name: 'aaa',
age: 18
}
(七) 函数和函数返回值
// 指定返回值为number
function add(x: number, y: number):number {
return x + y;
}
// 指定myADD为函数,且返回的是数字
let myAdd: (x:number, y:number)=>number =
function(x: number, y: number): number { return x+y; };
// 返回值为void(空)
function add(x: number, y: number): void {
let sum = x+y;
console.log(sum);
}
// lastName为可选参数
function buildName(firstName: string, lastName?: string) :voild{
console.log(firstName,lastName)
}
buildName('hu'); // hu,undefined
07 泛型
TS中泛型的实现使我们能够创建可重用的组件,一个组件可以支持多种类型的数据,为代码添加额外的抽象层和可重用性。泛型可以应用于TS中的函数、接口和类。
// 代码的意思传入一个叫做arg的参数,它是数字类型, 然后返回类型也是数字类型 function identity(arg: number): number { return arg; }
泛型可以理解为变量的类型, 它会自动判断传入的参数, 然后确定其类型
<>表示使用了泛型
arg:T 表示agr参数的类型是T
function identity<T>(arg: T): T { return arg; }
调用
let output = identity<string>("myString"); let output = identity("myString"); // 也可以这么写
08 类和继承
class Animal {
name: string;
constructor(theName: string) { this.name = theName; }
move(distanceInMeters: number = 0) {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}
class Snake extends Animal {
constructor(name: string) { super(name); }
move(distanceInMeters = 5) {
console.log("Slithering...");
super.move(distanceInMeters);
}
}
class Horse extends Animal {
constructor(name: string) { super(name); }
move(distanceInMeters = 45) {
console.log("Galloping...");
super.move(distanceInMeters);
}
}
let sam = new Snake("Sammy the Python");
let tom: Animal = new Horse("Tommy the Palomino");
sam.move();
tom.move(34);
09 模块导入导出(和Es6一样)
(1) 导出 m.ts
// 导出方式1
export let a = 20;
export let b = 50;
// 导出方式2
let a = 20;
let b = 50;
export {
a,
b
}
// 导出方式3
export default {
a:2,
b:3
}
(2) 导入 index.ts
// 导入方式1, 对应导出方式1和2
import {a} from './m'
import * as obj from './m'
// 导入方式2, 对应导出方式3
import obj from './m'
10 混入
// 混入对象1
class Bird {
canFly: boolean;
fly() {
this.canFly = true;
console.log('I can fly')
}
}
// 混入对象2
class Fish {
canSwim: boolean;
swim() {
this.canSwim = true;
console.log('I can swim')
}
}
// 新对象
class FlyFish implements Bird, Fish {
constructor() {
}
canFly:boolean= false;
canSwim:boolean= false;
fly: () => void;
swim: () => void;
}
function doMixins(derivedCtor: any, baseCtors: any[]) {
baseCtors.forEach(baseCtor => {
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
derivedCtor.prototype[name] = baseCtor.prototype[name];
});
});
}
doMixins(FlyFish, [Bird, Fish]);
let flyFish = new FlyFish();
console.log(flyFish.canFly);
flyFish.swim();